package com.xinchuang.util;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.locationtech.jts.geom.Coordinate;

/**
 * TODO
 *
 * @author zkwczx
 * @version 1.0
 * @date 2024/5/16 16:33
 */
public class Area {

    /**
     * 地球半径（米）
     * 6371000.0 ~ 6371009.0
     */
    private static double earthRadiusMeters = 6371006.0;

    /**
     * 米每度
     */
    private static double metersPerDegree = 2.0 * Math.PI * earthRadiusMeters / 360.0;

    /**
     * 弧度每度
     */
    private static double radiansPerDegree = Math.PI / 180.0;

    /**
     * 度每弧度
     */
    private static double degreesPerRadian = 180.0 / Math.PI;

    public static double getPosition(String plotinfoobj) {
        if (StringUtils.isBlank(plotinfoobj)) {
            return 0;
        }
        try {
            JSONObject json = JSONObject.parseObject(plotinfoobj);
            String type = json.getString("type");
            if (StringUtils.isBlank(type)) {
                return 0;
            }
            if ("SMGeoRectangle".equals(type)) {
                JSONArray positions = json.getJSONArray("positions");
                double minLon = 0;
                double maxLon = 0;
                double minLat = 0;
                double maxLat = 0;
                double lon = 0;
                double lat = 0;
                {
                    JSONArray array = positions.getJSONArray(0);
                    lon = array.getDouble(0);
                    lat = array.getDouble(1);
                    minLon = lon;
                    maxLon = lon;
                    minLat = lat;
                    maxLat = lat;
                }
                {
                    JSONArray array = positions.getJSONArray(1);
                    lon = array.getDouble(0);
                    lat = array.getDouble(1);
                    if (lon > minLon) {
                        maxLon = lon;
                    } else {
                        minLon = lon;
                    }
                    if (lat > minLat) {
                        maxLat = lat;
                    } else {
                        minLat = lat;
                    }
                }
                {
                    double[][] ddd = new double[5][2];
                    ddd[0][0] = minLon;
                    ddd[0][1] = maxLat;
                    ddd[1][0] = maxLon;
                    ddd[1][1] = maxLat;
                    ddd[2][0] = maxLon;
                    ddd[2][1] = minLat;
                    ddd[3][0] = minLon;
                    ddd[3][1] = minLat;
                    ddd[4][0] = minLon;
                    ddd[4][1] = maxLat;
                    return calculate(ddd);
                }
            } else if ("GeoPolygon".equals(type)) {
                JSONArray positions = json.getJSONArray("positions");
                double[][] ddd = new double[positions.size() + 1][2];
                double lon = 0;
                double lat = 0;
                for (int i = 0; i < positions.size(); i++) {
                    JSONArray array = positions.getJSONArray(i);
                    if (i == 0) {
                        lon = FileElseUtil.getStringTransitionDouble(array.get(0).toString());
                        lat = FileElseUtil.getStringTransitionDouble(array.get(1).toString());
                    }
                    ddd[i][0] = FileElseUtil.getStringTransitionDouble(array.get(0).toString());
                    ddd[i][1] = FileElseUtil.getStringTransitionDouble(array.get(1).toString());
                }
                ddd[positions.size()][0] = lon;
                ddd[positions.size()][1] = lat;
                return calculate(ddd);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static double calculate(String plotinfoobj) {
        if (StringUtils.isBlank(plotinfoobj)) {
            return 0;
        }
        try {
            JSONObject json = JSONObject.parseObject(plotinfoobj);
            if (CollectionUtil.isNotEmpty(json.getJSONArray("positions"))) {
                JSONArray positions = json.getJSONArray("positions");
                double[][] ddd = new double[positions.size() + 1][2];
                double lon = 0;
                double lat = 0;
                for (int i = 0; i < positions.size(); i++) {
                    JSONArray array = positions.getJSONArray(i);
                    if (i == 0) {
                        lon = FileElseUtil.getStringTransitionDouble(array.get(0).toString());
                        lat = FileElseUtil.getStringTransitionDouble(array.get(1).toString());
                    }
                    ddd[i][0] = FileElseUtil.getStringTransitionDouble(array.get(0).toString());
                    ddd[i][1] = FileElseUtil.getStringTransitionDouble(array.get(1).toString());
                }
                ddd[positions.size()][0] = lon;
                ddd[positions.size()][1] = lat;
                double area = calculate(ddd);
                System.out.println(area * 0.000001);
                return area;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;



//        if (StringUtils.isBlank(coordinate)) {
//            return "";
//        }
//        try {
//            double area = 0;
//            for (String group : coordinate.split("&&")) {
//                String[] ss = group.split("\\|");
//                double[][] ddd = new double[ss.length][2];
//                for (int i=0;i< ss.length;i++) {
//                    String[] lnglat = ss[i].split(",");
//                    ddd[i][0] = Double.valueOf(lnglat[0]).doubleValue();
//                    ddd[i][1] = Double.valueOf(lnglat[1]).doubleValue();
//                }
//                area += calculate(ddd);
//            }
////            return toFix2(area * 0.000001) + "平方公里";
////            return toFix2(area ) + "平方米";
//            return toFix2(area ) ;
//        } catch (Exception e) {
//            e.printStackTrace();
//            return "";
//        }
    }

    public static double calculate(double[][] group) {
        // 平面多边形面积
        double areaMeters2 = planarPolygonAreaMeters2(group);
        if (areaMeters2 > 1000000.0) {
            // 球面多边形面积计算
            areaMeters2 = sphericalPolygonAreaMeters2(group);
        }
        return areaMeters2;
    }

    private static String toFix2(double area) {
        String value = String.format("%.02f", area);
        while (true) {
            if (value.endsWith("0")) {
                value = value.substring(0, value.length() -1);
                continue;
            }
            if (value.endsWith(".")) {
                value = value.substring(0, value.length() -1);
                break;
            }
            break;
        }
        return value;
    }

    /**
     * 平面多边形面积
     */
    public static double planarPolygonAreaMeters2(double[][] group) {
        double a = 0;
        for (int i = 0; i < group.length; i++) {
            int j = (i + 1) % group.length;
            double[] point_i = group[i];
            double xi = point_i[0] * metersPerDegree * Math.cos(point_i[1] * radiansPerDegree);
            double yi = point_i[1] * metersPerDegree;
            double[] point_j = group[j];
            double xj = point_j[0] * metersPerDegree * Math.cos(point_j[1] * radiansPerDegree);
            double yj = point_j[1] * metersPerDegree;
            a += xi * yj - xj * yi;
        }
        // 转化为正数
        return Math.abs(a / 2);
    }

    /**
     * 球面多边形面积计算
     */
    public static double sphericalPolygonAreaMeters2(double[][] group) {
        // 总角度
        double totalAngle = 0;
        int size = group.length;
        for (int i = 0; i < group.length; i++) {
            int j = (i + 1) % size;
            int k = (i + 2) % size;
            totalAngle += angle(group[i], group[j], group[k]);
        }
        // 平面总角度
        double planarTotalAngle = (size - 2) * 180.0;
        // 球形过剩
        double sphericalExcess = totalAngle - planarTotalAngle;
        if (sphericalExcess > 420.0) {
            totalAngle = size * 360.0 - totalAngle;
            sphericalExcess = totalAngle - planarTotalAngle;
        } else if (sphericalExcess > 300.0 && sphericalExcess < 420.0) {
            sphericalExcess = Math.abs(360.0 - sphericalExcess);
        }
        return sphericalExcess * radiansPerDegree * earthRadiusMeters * earthRadiusMeters;
    }

    /**
     * 角度
     */
    public static double angle(double[] point1, double[] point2, double[] point3) {
        double bearing21 = bearing(point2, point1);
        double bearing23 = bearing(point2, point3);
        double angle = bearing21 - bearing23;
        if (angle < 0) {
            angle += 360;
        }
        return angle;
    }

    /**
     * 方向
     */
    public static double bearing(double[] from, double[] to) {
        double lat1 = from[0] * radiansPerDegree;
        double lon1 = from[1] * radiansPerDegree;
        double lat2 = to[1] * radiansPerDegree;
        double lon2 = to[0] * radiansPerDegree;
        double angle = -Math.atan2(
                Math.sin(lon1 - lon2) * Math.cos(lat2),
                Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
        if (angle < 0) {
            angle += Math.PI * 2.0;
        }
        angle = angle * degreesPerRadian;
        return angle;
    }

}
